﻿using System;
using System.Collections;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using OrganizedConfusion.Game_Objects;

namespace OrganizedConfusion
{
    /// <summary>
    /// Internal texture struct used to hold texture data
    /// </summary>
    struct TextureStruct
    {
        public Texture2D tex;
        public string path;
        public int count;
    }

    public class ContentsManager
    {
        ContentManager content;
        List<TextureStruct> Textures;

        ContentsManager() { Textures = new List<TextureStruct>(); }

        static ContentsManager instance = new ContentsManager();
        
        /// <summary>
        /// Returns an instance of the Content Manager singleton.
        /// </summary>
        public static ContentsManager Instance
        {
            get { return instance; }
        }

        /// <summary>
        ///  Called at the beginning of the program. Initilizes the content manager.
        /// </summary>
        /// <param name="cm"></param>
        public void InitContentsManager(ContentManager cm, IServiceProvider ISP)
        {
            if (content == null)
                content = new ContentManager(ISP, "Content");
        }

        /// <summary>
        /// Only call this when exiting the game.
        /// </summary>
        public void ShutdownContentsManager()
        {
            //content.Dispose();
            content.Unload();
            Textures.Clear();
        }

        /// <summary>
        /// Loads a texture to content manager and returns its index. If the texture exists, it only increments the number of objects associated with it.
        /// </summary>
        /// <param name="TexturePath"></param>
        /// <returns>The texture's index</returns>
        public int LoadTexture(string TexturePath)
        {
            TextureStruct ts = new TextureStruct();
            ts.path = TexturePath;

            for (int i = 0; i < Textures.Count; i++)
            {
                if (Comparer<string>.Equals(Textures[i].path, ts.path))
                {
                    ts.count = Textures[i].count + 1;
                    ts.tex = Textures[i].tex;
                    Textures[i] = ts;
                    return i;
                }
            }

            ts.tex = content.Load<Texture2D>(TexturePath);
            ts.count = 1;
            Textures.Add(ts);
            return Textures.Count - 1;
        }

        /// <summary>
        /// Draw call for the texture.
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public Texture2D Draw(int index)
        {
            try
            {
                return Textures[index].tex;
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// Gets the width and height of the texture for the index passed in.
        /// </summary>
        /// <param name="index"></param>
        /// <returns>Width/Height in a vector</returns>
        public Vector2 GetImageDimensions(int index)
        {
            return new Vector2(Textures[index].tex.Width, Textures[index].tex.Height);
        }

        /// <summary>
        /// Removes a reference to the texture. If there is only one reference, the texture is removed from list, but deleted randomly by garbage collector.
        /// </summary>
        /// <param name="index"></param>
        public void UnloadTexture(int index)
        {
            try
            {
                if (Textures[index].count > 1)
                {
                    TextureStruct ts = Textures[index];
                    ts.count--;
                    Textures[index] = ts;
                }
                else if (Textures[index].count == 1)
                {
                    Textures.RemoveAt(index);
                }
            }
            catch
            {
                return;
            }
        }
    }
}
